package org.smarthings.things.management.impl.metadata.provider;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.smarthings.things.management.event.ThingEventConstants;
import org.smarthings.things.management.metadata.provider.ThingEventMetadataProvider;

@Component(immediate = true)
@Service(ThingEventMetadataProvider.class)
public class DefaultThingEventMetadataProvider implements ThingEventMetadataProvider {

	private Map<String, Map<String, Object>> topics = new HashMap<String, Map<String, Object>>(4);

	public DefaultThingEventMetadataProvider() {

		Map<String, Object> thing = new HashMap<String, Object>(5);
		thing.put(ThingEventConstants.PROPERTY_THING_UUID, String.class);
		thing.put(ThingEventConstants.PROPERTY_THING_NAME, String.class);
		thing.put(ThingEventConstants.PROPERTY_THING_TYPE, String.class);
//		thing.put(ThingEventConstants.PROPERTY_THING_TAGS, String[].class);
		thing.put(ThingEventConstants.PROPERTY_THING_STATE, Integer.class);

		Map<String, Object> property = new HashMap<String, Object>(10);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_UUID, String.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_TYPE, String.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_STRING, String.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_BOOLEAN, Boolean.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_INTEGER, Integer.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_LONG, Long.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_FLOAT, Float.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_DOUBLE, Double.class);
		property.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY_VALUE_PREFIX
				+ ThingEventConstants.PROPERTY_TYPE_BIG_INTEGER, BigInteger.class);

		Map<String, Object> action = new HashMap<String, Object>(5);
		action.put(ThingEventConstants.PROPERTY_THING_EXECUTED_ACTION_UUID, String.class);
		action.put(ThingEventConstants.PROPERTY_THING_EXECUTED_ACTION_TYPE, String.class);
//		action.put(ThingEventConstants.PROPERTY_THING_EXECUTED_ACTION_ARGUMENTS, String.class);
		// action arguments are not of interest for the rule engine and event processing engines for
		// demo!

		Map<String, Object> metadata = new HashMap<String, Object>(2);
		metadata.put(ThingEventConstants.PROPERTY_THING, thing);
		metadata.put(ThingEventConstants.PROPERTY_TIMESTAMP, Long.class);
		this.topics.put(ThingEventConstants.TOPIC_THING_REGISTERED, metadata);

		metadata = new HashMap<String, Object>(2);
		metadata.put(ThingEventConstants.PROPERTY_THING, thing);
		metadata.put(ThingEventConstants.PROPERTY_TIMESTAMP, Long.class);
		this.topics.put(ThingEventConstants.TOPIC_THING_UNREGISTERED, metadata);

		metadata = new HashMap<String, Object>(2);
		metadata.put(ThingEventConstants.PROPERTY_THING, thing);
		metadata.put(ThingEventConstants.PROPERTY_TIMESTAMP, Long.class);
		this.topics.put(ThingEventConstants.TOPIC_THING_STATE_CHANGED, metadata);

		metadata = new HashMap<String, Object>(3);
		metadata.put(ThingEventConstants.PROPERTY_THING, thing);
		metadata.put(ThingEventConstants.PROPERTY_THING_CHANGED_PROPERTY, property);
		metadata.put(ThingEventConstants.PROPERTY_TIMESTAMP, Long.class);
		this.topics.put(ThingEventConstants.TOPIC_THING_PROPERTY_CHNAGED, metadata);
		
		metadata = new HashMap<String, Object>(3);
		metadata.put(ThingEventConstants.PROPERTY_THING, thing);
		metadata.put(ThingEventConstants.PROPERTY_THING_EXECUTED_ACTION, action);
		metadata.put(ThingEventConstants.PROPERTY_TIMESTAMP, Long.class);
		this.topics.put(ThingEventConstants.TOPIC_THING_ACTION_EXECUTED, metadata);
	}

	public List<String> getThingEventTopics() {
		return new ArrayList<String>(topics.keySet());
	}

	public Map<String, Object> getThingEventDescription(String topic) {
		return topics.get(topic);
	}
}
